package com.xyq.fs.search;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.util.ArrayList;
import java.util.Date;

import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;

import com.xyq.fs.base.MyDirectoryS;
import com.xyq.fs.constants.FieldConstant;
import com.xyq.fs.constants.IndexStringConstants;
import com.xyq.fs.entity.MyFile;

import com.xyq.fs.views.WindowsGo;

public class MySearch {

	private static String[] QUERIES_INDEX_NAMES = { FieldConstant.FILE_NAME, FieldConstant.FILE_CONTENT };

	private static List<Query> QBLX_SIMPLE_TERMQUERY = new ArrayList<Query>();
	private static List<Query> QBLX_TERMQUERY = new ArrayList<Query>();
	private static TermQuery QT = new TermQuery(new Term(FieldConstant.FILE_SUFFIX, IndexStringConstants.QT));
	private static TermQuery QT2 = new TermQuery(new Term(FieldConstant.FILE_SUFFIX, IndexStringConstants.QT2));

	public static int SEARCH_NUM = Integer.MAX_VALUE;

	static {
		IndexStringConstants.simpleSuffixList.forEach(s -> {
			QBLX_SIMPLE_TERMQUERY.add(new TermQuery(new Term(FieldConstant.FILE_SUFFIX, s)));
		});
		IndexStringConstants.suffixList.forEach(s -> {
			QBLX_TERMQUERY.add(new TermQuery(new Term(FieldConstant.FILE_SUFFIX, s)));
		});
	}

	private static BooleanQuery.Builder SELECT_BQ_BU = new BooleanQuery.Builder();
	private static BooleanQuery.Builder NOSELECT_BQ_BU = new BooleanQuery.Builder();

	static {
		QBLX_SIMPLE_TERMQUERY.forEach(q -> {
			SELECT_BQ_BU.add(q, BooleanClause.Occur.SHOULD);
		});
		QBLX_TERMQUERY.forEach(q -> {
			NOSELECT_BQ_BU.add(q, BooleanClause.Occur.SHOULD);
		});
		NOSELECT_BQ_BU.add(QT, BooleanClause.Occur.SHOULD);
	}

	private static BooleanQuery SELECT_BQ = SELECT_BQ_BU.build();
	private static BooleanQuery NOSELECT_BQ = NOSELECT_BQ_BU.build();

	/**
	 * 生成一个查询query s
	 * 
	 * @param page
	 * @return
	 */
	public static Query buildQuery(SearchBody body) {

		BooleanQuery.Builder bQuery = new BooleanQuery.Builder();
		// 构建常规查询
		for (String key : body.getSearchKeys()) {
			BooleanQuery.Builder bQuery2 = new BooleanQuery.Builder();
			for (int y = 0; y < QUERIES_INDEX_NAMES.length; y++) {
				Query query2 = new PhraseQuery(0, QUERIES_INDEX_NAMES[y], key.split(""));
				bQuery2.add(query2, BooleanClause.Occur.SHOULD);
			}
			bQuery.add(bQuery2.build(), BooleanClause.Occur.FILTER);
		}
		if (body.getNoSearchKeys() != null)
			// 不扫描列表
			for (String key : body.getNoSearchKeys()) {
				for (int y = 0; y < QUERIES_INDEX_NAMES.length; y++) {
					Query query2 = new PhraseQuery(0, QUERIES_INDEX_NAMES[y], key.split(""));
					bQuery.add(query2, BooleanClause.Occur.MUST_NOT);
				}
			}
		String va = WindowsGo.cboxB.getValue();
		// 是否盘符搜索
		if (!IndexStringConstants.SYPF.equals(va)) {
			TermQuery tq = new TermQuery(new Term(FieldConstant.FILE_PANFU, va));
			bQuery.add(tq, BooleanClause.Occur.FILTER);
			tq = null;
		}
		va = WindowsGo.cboxA.getValue();
		switch (va) {
		case IndexStringConstants.QBLX:
			if (WindowsGo.rbtnB.isSelected()) {
				bQuery.add(SELECT_BQ, BooleanClause.Occur.FILTER);
			} else {
				bQuery.add(NOSELECT_BQ, BooleanClause.Occur.FILTER);
			}
			break;
		case IndexStringConstants.QT:
			bQuery.add(QT, BooleanClause.Occur.FILTER);
			break;
		case IndexStringConstants.QT2:
			bQuery.add(QT2, BooleanClause.Occur.FILTER);
			break;

		default:
			TermQuery tq = new TermQuery(new Term(FieldConstant.FILE_SUFFIX, va));
			bQuery.add(tq, BooleanClause.Occur.FILTER);
			break;
		}
		if (body.getStartDate() != null && body.getEndDate() != null) {
			Query querys = LongPoint.newRangeQuery(FieldConstant.FILE_UPDATE_TIME, body.getStartDate().getTime(),
					body.getEndDate().getTime());
			bQuery.add(querys, BooleanClause.Occur.FILTER);
		}
		return bQuery.build();
		// 自定义排序
		// return FunctionScoreQuery.boostByQuery(bQuery.build());

	}

	/**
	 * 分页查询
	 * 
	 * @param page
	 */
	private static SortField sortField = new SortField(FieldConstant.FILE_UPDATE_TIME, SortField.Type.LONG, true);
	private static Sort sort = new Sort(sortField);

	public static MyFile search(boolean isHasFirst, Query query, ScoreDoc after) {

		MyFile page = new MyFile();
		int pageSize = page.getPageSize();
		TopDocs docs = null;
		IndexSearcher searcher = MyDirectoryS.getIndexSearcher();
		try {
			if (after == null) {
				if (isHasFirst) {
					docs = searcher.search(query, pageSize, sort);
				} else {
					docs = searcher.search(query, SEARCH_NUM, sort);
					page.setTotalResultNum(docs.scoreDocs.length);
				}
			} else {
				docs = searcher.searchAfter(after, query, pageSize, sort);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		int len = docs.scoreDocs.length;
		int tempSize = (len > pageSize ? pageSize : len);
		for (int i = 0; i < tempSize; i++) {
			ScoreDoc sdoc = docs.scoreDocs[i];
			if (i == tempSize - 1) {
				page.setAfterScoreDoc(sdoc);
			}
			try {
				Document doc = searcher.doc(sdoc.doc);
				page.getDocList().add(doc);
				doc = null;
			} catch (Exception e) {
				// MyDirectoryS.updateReaderAndSearcher();
			}
		}
		return page;
	}

	public static void delOld() {

		System.out.println("开始清理");
		SearchBody body = new SearchBody();
		body.setSearchKeys(new String[] { "." });
		Query query = buildQuery(body);
		try {
			IndexSearcher searcher = MyDirectoryS.getIndexSearcher();
			ScoreDoc doc;
			Document docc;
			TopDocs docs = searcher.search(query, Integer.MAX_VALUE);
			Path path;
			String pathStr;
			for (int i = 0; i < docs.scoreDocs.length; i++) {

				if (WindowsGo.SLEEP_NOW == 4)
					break;
				doc = docs.scoreDocs[i];
				docc = searcher.doc(doc.doc);
				pathStr = docc.get(FieldConstant.FILE_PATH);
				path = Paths.get(pathStr);
				if (!Files.exists(path)) {
					Term term = new Term(FieldConstant.FILE_PATH, pathStr);
					MyDirectoryS.writer.deleteDocuments(term);
					term = null;
				}
				docc.clear();
				docc = null;
			}
			docs = null;
			pathStr = null;
			doc = null;
			query = null;
			body = null;
			System.out.println("清理完毕");

		} catch (IOException e) {

			e.printStackTrace();
		}
	}

	public static void main(String[] args) {

		System.out.println(new Date().getTime());
	}
}
